using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Transactions;
using T.FAS.Runtime.DataAccess.Common;
using T.FAS.Runtime.DataAccess.SPI;
using T.FAS.Runtime.DataAccess.SQLDom;
using T.FAS.Runtime.Metadata.Entity.DataModel;
using T.ServiceComponent.DataAccessEx.Core;
using T.ServiceComponent.Error;
using T.ServiceComponent.Monitor.Client;
using T.ServiceComponent.Runtime.Common;
using T.FAS.Runtime.Base.Entity;
using Npgsql;
using NpgsqlTypes;

namespace T.FAS.Runtime.DataAccess.Kernel
{
    /// <summary>
    /// 内部数据访问服务
    /// </summary>
    class DatabaseImpl : IDatabase
    {
        public event BeforeSQLExecute BeforeSQLExecute;
        public event ExecuteSQLSuccess ExecuteSQLSuccessed;
        private readonly IDACLogService _localLogService = DACLogFactory.GetDACLogService();
        internal static ITDatabase MockDataBase { get; set; } = null;

        #region 获取DB实例
        /// <summary>
        /// 获取数据库服务
        /// </summary>
        /// <param name="dataSourceName">数据源</param>
        /// <returns>数据库服务</returns>
        public ITDatabase GetDatabase(string dataSourceName = "")
        {
            return TDatabaseFactory.GetDataBase(dataSourceName);
        }

        /// <summary>
        /// 通过配置中心获取数据库服务
        /// </summary>
        /// <param name="configkey">配置key</param>
        /// <returns>数据库服务</returns>
        public ITDatabase GetDatabaseByConfigkey(string configkey)
        {
            try
            {
                if (MockDataBase != null) return MockDataBase;
                var db = DatabaseHelper.GetDatabaseByConnectionKey(configkey);
                if (db == null)
                    throw new FasException(DataAccessErrorCode.Database.ConfigKeyError, string.Format(CommonStringClassKernel.DatabaseImpl_GetDatabaseByConfigkey, configkey));
                return db;
            }
            catch (Exception e)
            {
                throw new FasException(DataAccessErrorCode.Database.ConfigKeyError, string.Format(CommonStringClassKernel.DatabaseImpl_GetDatabaseByConfigkey1, configkey), e);
            }
        }


        #endregion

        #region 执行SQL取数方法_基于SqlStatement
        /// <summary>
        /// 执行SQL获取数据
        /// </summary>
        /// <param name="sql">SQL语句</param>
        /// <returns>数据</returns>
        public DataSet GetData(SqlStatement sql)
        {
            if (sql == null)
                throw new FasException(DataAccessErrorCode.Database.NullValue, CommonStringClassKernel.SqlCannotBeNull);
            var sqlStrings = sql.ToSQL();
            var tableNames = sql.TableName;
            var controlContext = GetControlContext(sql);
            return GetData(sql.DatabaseConfigKey, sqlStrings, tableNames, controlContext);
        }

        /// <summary>
        /// 执行SQL获取数据
        /// </summary>
        /// <param name="sql">SQL语句</param>
        /// <returns>数据</returns>
        public DataSet GetData(SqlStatement sql, Dictionary<string, object> paramList)
        {
            if (sql == null)
                throw new FasException(DataAccessErrorCode.Database.NullValue, CommonStringClassKernel.SqlCannotBeNull);

            var sqlStrings = sql.ToSQL();
            var tableNames = sql.TableName;
            List<IDbDataParameter> param = null;
            if (paramList != null)
            {
                param = new List<IDbDataParameter>();
                var db = GetDatabaseByConfigkey(sql.DatabaseConfigKey);
                foreach (var item in paramList)
                {
                    db.MakeInParam(item.Key, item.Value);
                }
            }

            var controlContext = GetControlContext(sql);
            if (param == null)
            {
                return GetData(sql.DatabaseConfigKey, sqlStrings, tableNames, controlContext);
            }
            else
            {
                var inParam = param.ToArray();
                return GetData(sql.DatabaseConfigKey, sqlStrings, tableNames, inParam, controlContext);
            }
        }

        /// <summary>
        /// 执行SQL获取数据
        /// </summary>
        /// <param name="sql">SQL语句</param>
        /// <returns>数据</returns>
        public List<DataTable> GetDataCollection(SqlStatementCollection sqls)
        {
            if (sqls == null)
                throw new FasException(DataAccessErrorCode.Database.NullValue, CommonStringClassKernel.SqlCannotBeNull);

            var dataTables = new List<DataTable>();
            var sqlGroups = sqls.GroupBy(i => i.DatabaseConfigKey);

            try
            {
                foreach (var sqlGroup in sqlGroups)
                {
                    if (sqlGroup.Count() == 0) continue;
                    SqlStatement sqlStatement = sqlGroup.FirstOrDefault();
                    var dataSourceName = sqlStatement.DatabaseConfigKey;
                    var db = GetDatabaseByConfigkey(dataSourceName);
                    foreach (var sqlstatment in sqlGroup)
                    {
                        var sqlString = sqlstatment.ToSQL();
                        var extInfo = GetControlContext(sqlstatment);
                        if (extInfo != null && extInfo.ContainsKey(DACConst.DACControlContextConst.Timeout))
                        {
                            var timeout = (int)extInfo[DACConst.DACControlContextConst.Timeout];
                            if (timeout > 0)
                            {
                                //执行超时时间控制
                            }
                        }

                        try
                        {
                            DataSet ds;
                            var parameters = new List<IDbDataParameter>();
                            if (sqlstatment is SelectSqlStatement)
                                parameters = ParameterHandlerForSelect(sqlstatment, db);
                            var extParams = new ExtLogInfo { MetaDataCode = sqlStatement.MetaDataCode };
                            string traceSQL = $"dataSource:{dataSourceName}查询SQL输出=========>：" + sqlString;
                            if (!string.IsNullOrEmpty(sqlStatement.MetaDataCode))
                            {
                                traceSQL = $"metaDataCode:{sqlStatement.MetaDataCode}," + traceSQL;
                            }
                            _localLogService.WriteSQL(traceSQL, parameters?.ToArray(), SQLLogType.DQL, extParams);

                            if (parameters == null || parameters.Count == 0)
                            {
                                ds = db.ExecuteDataSet(sqlString);
                            }
                            else
                            {
                                ds = db.ExecuteDataSet(sqlString, parameters.ToArray());
                            }

                            if (ds != null)
                            {
                                //非分页查询只返回单个Table
                                if (ds.Tables.Count == 1)
                                {
                                    ds.Tables[0].TableName = sqlstatment.SqlBuildingInfo.CurrentNode.DataObjectTableAlias;
                                    dataTables.Add(ds.Tables[0]);
                                }
                                else if (ds.Tables.Count == 2)
                                {
                                    ds.Tables[0].TableName = sqlstatment.SqlBuildingInfo.CurrentNode.DataObjectTableAlias;
                                    dataTables.Add(ds.Tables[0]);
                                    ds.Tables[1].TableName = sqlstatment.SqlBuildingInfo.CurrentNode.DataObjectTableAlias + "_TotalCount";
                                    dataTables.Add(ds.Tables[1]);
                                }
                            }
                        }
                        catch (Exception e)
                        {
                            MonitorError(e, sqlString);
                            throw;
                        }
                    }
                }
                return dataTables;
            }
            catch (Exception e)
            {
                MonitorError(e, new string[sqls.Count]);
                throw;
            }
        }

        /// <summary>
        /// 执行SQL返回IDataReader
        /// </summary>
        /// <param name="sql">SQL语句</param>
        /// <returns>IDataReader</returns>
        public IDataReader GetDataReader(SqlStatement sql)
        {
            var sqlStrings = sql.ToSQL();
            var extInfo = GetControlContext(sql);
            if (extInfo != null && extInfo.ContainsKey(DACConst.DACControlContextConst.Timeout))
            {
                var timeout = (int)extInfo[DACConst.DACControlContextConst.Timeout];
                if (timeout > 0)
                {
                    //执行超时时间控制
                }
            }
            var db = GetDatabaseByConfigkey(sql.DatabaseConfigKey);
            try
            {
                return db.ExecuteReader(sqlStrings);
            }
            catch (Exception e)
            {
                MonitorError(e, sqlStrings);
                throw;
            }
        }

        /// <summary>
        /// 执行SQL获取数据的第一行第一列
        /// </summary>
        /// <param name="sql">SQL语句</param>
        /// <returns>数据的第一行第一列</returns>
        public object ExecuteScalar(SqlStatement sql)
        {
            var sqlStrings = sql.ToSQL();
            var db = GetDatabaseByConfigkey(sql.DatabaseConfigKey);
            try
            {
                var extInfo = GetControlContext(sql);
                if (extInfo != null && extInfo.ContainsKey(DACConst.DACControlContextConst.Timeout))
                {
                    var timeout = (int)extInfo[DACConst.DACControlContextConst.Timeout];
                    if (timeout > 0)
                    {
                        //执行超时时间控制
                    }
                }
                return db.ExecuteScalar(sqlStrings);
            }
            catch (Exception e)
            {
                MonitorError(e, sqlStrings);
                throw;
            }
        }
        #endregion

        #region 执行SQL取数方法_基于ELB组件
        /// <summary>
        /// 获取数据
        /// </summary>
        /// <param name="dataSourceName"></param>
        /// <param name="sqlString"></param>
        /// <param name="tableName"></param>
        /// <param name="extInfo"></param>
        /// <returns></returns>
        /// <exception cref="FasException"></exception>
        public DataSet GetData(string dataSourceName, string sqlString, string tableName, Dictionary<string, object> extInfo = null)
        {
            if (string.IsNullOrEmpty(sqlString) || string.IsNullOrEmpty(dataSourceName) || string.IsNullOrEmpty(tableName))
                throw new FasException(DataAccessErrorCode.Database.NullValue, CommonStringClassKernel.SqlCannotBeNull);

            var db = GetDatabaseByConfigkey(dataSourceName);
            _localLogService.WriteSQL($"dataSource:{dataSourceName},查询SQL输出=========>：\r\n" + sqlString);
            if (db == null || db.DbProviderFactory == null)
                throw new FasException(DataAccessErrorCode.Database.CanNotGetDBInstanceError, CommonStringClassKernel.DatabaseImpl_CannotGetDatabaseConn + dataSourceName);
            try
            {
                if (extInfo != null && extInfo.ContainsKey(DACConst.DACControlContextConst.Timeout))
                {
                    var timeout = (int)extInfo[DACConst.DACControlContextConst.Timeout];
                    if (timeout > 0)
                    {
                        //执行超时时间控制
                    }
                }
                DataSet dataset = db.ExecuteDataSet(sqlString);
                if (dataset != null && dataset.Tables.Count > 0)
                    dataset.Tables[0].TableName = tableName;
                return dataset;
            }
            catch (Exception e)
            {
                MonitorError(e, new string[] { sqlString });
                throw;
            }
        }

        /// <summary>
        /// 获取数据
        /// </summary>
        /// <param name="dataSourceName">数据源名称</param>
        /// <param name="sqlString">SQL语句</param>
        /// <param name="tableName">表名称</param>
        /// <param name="dbDataParameters"></param>
        /// <param name="extInfo"></param>
        /// <returns>数据集</returns>
        /// <exception cref="FasException"></exception>
        public DataSet GetData(string dataSourceName, string sqlString, string tableName, IDbDataParameter[] dbDataParameters, Dictionary<string, object> extInfo = null)
        {
            if (string.IsNullOrEmpty(sqlString) || string.IsNullOrEmpty(dataSourceName) || string.IsNullOrEmpty(tableName))
                throw new FasException(DataAccessErrorCode.Database.NullValue, CommonStringClassKernel.SqlCannotBeNull);

            var db = GetDatabaseByConfigkey(dataSourceName);
            string metaDataCode = null;
            if (extInfo != null && extInfo.TryGetValue("MetaDataCode", out object metaDataCodeObj))
            {
                metaDataCode = metaDataCodeObj?.ToString();
            }
            var extParams = new ExtLogInfo { MetaDataCode = metaDataCode };
            string traceSQL = $"dataSource:{dataSourceName},查询SQL输出=========>：\r\n" + sqlString;
            if (!string.IsNullOrEmpty(metaDataCode))
            {
                traceSQL = $"metaDataCode:{metaDataCode}," + traceSQL;
            }
            _localLogService.WriteSQL(traceSQL, dbDataParameters?.ToArray(), SQLLogType.DQL, extParams);
            if (db == null || db.DbProviderFactory == null)
                throw new FasException(DataAccessErrorCode.Database.CanNotGetDBInstanceError, CommonStringClassKernel.DatabaseImpl_CannotGetDatabaseConn + dataSourceName);
            try
            {
                if (extInfo != null && extInfo.ContainsKey(DACConst.DACControlContextConst.Timeout))
                {
                    var timeout = (int)extInfo[DACConst.DACControlContextConst.Timeout];
                    if (timeout > 0)
                    {
                        //执行超时时间控制
                    }
                }
                DataSet dataset = db.ExecuteDataSet(sqlString, dbDataParameters);
                if (dataset != null && dataset.Tables.Count > 0)
                    dataset.Tables[0].TableName = tableName;
                return dataset;
            }
            catch (Exception e)
            {
                MonitorError(e, new string[] { sqlString });
                throw;
            }
        }
        #endregion

        #region 执行DML SQL
        /// <summary>
        /// 在数据库事务中执行SQL语句返回影响行数，用于Create Update Delete方法
        /// </summary>
        /// <param name="sqls">SQL语句</param>        
        public void ExecuteSQLWithTransaction(SqlStatementCollection sqls)
        {
            if (sqls == null)
                throw new FasException(DataAccessErrorCode.Database.NullValue, CommonStringClassKernel.SqlCannotBeNull);

            var sqlGroups = sqls.GroupBy(i => i.DatabaseConfigKey);
            if (sqlGroups.Count() == 0) return;
            var tmp = sqlGroups.FirstOrDefault()?.FirstOrDefault();
            var cdoId = tmp?.CommonObjectID;
            var dbConnectionKey = tmp?.DatabaseConfigKey;
            if (string.IsNullOrEmpty(dbConnectionKey))
            {
                throw new FasException(DataAccessErrorCode.CompositeDataObject.Error, string.Format(CommonStringClassKernel.DatabaseImpl_ExecuteSQLWithTransaction1, cdoId));
            }
            var db = GetDatabaseByConfigkey(dbConnectionKey);

            using (var trans = db.BeginTransaction())
            {
                try
                {
                    foreach (var sqlGroup in sqlGroups)
                    {
                        if (sqlGroup.Count() == 0) continue;
                        var dataSourceName = sqlGroup.FirstOrDefault().DatabaseConfigKey;

                        foreach (SqlStatement sqlStatment in sqlGroup)
                        {

                            string sqlString = sqlStatment.ToSQL();
                            Dictionary<string, object> controlContext = GetControlContext(sqlStatment);
                            if (controlContext != null && controlContext.ContainsKey(DACConst.DACControlContextConst.Timeout))
                            {
                                var timeout = (int)controlContext[DACConst.DACControlContextConst.Timeout];
                                if (timeout > 0)
                                {
                                    //执行超时时间控制
                                }
                            }

                            try
                            {
                                var parameters = new List<IDbDataParameter>();
                                parameters = CreateParameters(db, sqlStatment, parameters);
                                var extParams = new ExtLogInfo { MetaDataCode = sqlStatment.MetaDataCode };
                                _localLogService.WriteSQL($"dataSource:{dataSourceName}增删改SQL输出=========>：" + sqlString, parameters?.ToArray(), SQLLogType.DML, extParams);
                                int affectedRows;
                                if (parameters == null || parameters.Count == 0)
                                {
                                    affectedRows = db.ExecSqlStatement(sqlString);
                                }
                                else
                                {
                                    affectedRows = db.ExecSqlStatement(sqlString, parameters.ToArray());
                                }

                                //构造成功调用SQL后的参数，触发SQL执行后事件，因为sql执行受影响行数无法预估，所以受影响行数=0抛出异常不应该在本层处理
                                SQLExecuteContext sqlExecuteContext = new SQLExecuteContext
                                {
                                    SQL = sqlString,
                                    Parameters = parameters,
                                    SQLStatement = sqlStatment,
                                    SqlBuildingInfo = sqlStatment?.SqlBuildingInfo,
                                };
                                DatabaseExecuteReulst executeReulst = new DatabaseExecuteReulst
                                {
                                    AffectedRows = affectedRows,
                                    SQLExecuteContext = sqlExecuteContext,
                                };
                                ExecuteSQLSuccessed?.Invoke(executeReulst);
                            }
                            catch (Exception e)
                            {
                                MonitorError(e, sqlString);
                                throw;
                            }
                        }
                    }
                    trans.Commit();
                }
                catch (Exception e)
                {
                    trans.Rollback();
                    MonitorError(e, new string[sqls.Count]);
                    throw;
                }
            }
        }

        /// <summary>
        /// 处理sql集合中的参数，调用底层数据访问接口，返回受影响的行数据。
        /// </summary>
        /// <param name="sqls">待处理的SQL语句集合</param>
        /// <returns>受影响的行数据</returns>
        public void ExecuteSQLs(SqlStatementCollection sqls)
        {
            if (sqls == null)
                throw new FasException(DataAccessErrorCode.Database.NullValue, CommonStringClassKernel.SqlCannotBeNull);
            if (sqls.Count == 0)
                return;

            foreach (var sqlstatment in sqls)
            {
                var db = GetDatabaseByConfigkey(sqlstatment.DatabaseConfigKey);
                {
                    var sqlString = sqlstatment.ToSQL();
                    var controlContext = GetControlContext(sqlstatment);
                    if (controlContext != null && controlContext.ContainsKey(DACConst.DACControlContextConst.Timeout))
                    {
                        var timeout = (int)controlContext[DACConst.DACControlContextConst.Timeout];
                        if (timeout > 0)
                        {
                            //执行超时时间控制
                        }
                    }
                    try
                    {
                        var parameters = new List<IDbDataParameter>();

                        if (sqlstatment is InsertSqlStatement)
                            parameters = ParameterHandlerForInsert(sqlstatment, db);

                        else if (sqlstatment is UpdateSqlStatement)
                        {
                            parameters = ParameterHandlerForUpdate(sqlstatment, db);
                        }

                        if (parameters == null || parameters.Count == 0)
                        {
                            db.ExecSqlStatement(sqlString);
                        }
                        else
                        {
                            db.ExecSqlStatement(sqlString, parameters);
                        }
                    }
                    catch (Exception e)
                    {
                        MonitorError(e, sqlString);
                        throw;
                    }
                }
            }
        }
        #endregion

        #region 处理SQL参数
        private List<IDbDataParameter> CreateParameters(ITDatabase db, SqlStatement sqlStatement, List<IDbDataParameter> parameters)
        {
            if (sqlStatement is InsertSqlStatement)
                parameters = ParameterHandlerForInsert(sqlStatement, db);

            else if (sqlStatement is UpdateSqlStatement)
            {
                parameters = ParameterHandlerForUpdate(sqlStatement, db);
            }
            else if (sqlStatement is DeleteSqlStatement)
            {
                parameters = ParameterHandlerForDelete(sqlStatement, db);
            }

            return parameters;
        }

        /// <summary>
        /// 对Update类SQL语句进行参数处理
        /// </summary>
        /// <param name="sqlStatement">待处理的SQL语句</param>
        /// <param name="db">数据访问对象</param>
        /// <returns>处理后的参数数组</returns>
        private List<IDbDataParameter> ParameterHandlerForUpdate(SqlStatement sqlStatement, ITDatabase db)
        {
            var updateSql = sqlStatement as UpdateSqlStatement;
            var parameters = new List<IDbDataParameter>(updateSql.UpdateFields.ChildCollection.Count);

            for (int parameterIndex = 0; parameterIndex < updateSql.UpdateFields.ChildCollection.Count; parameterIndex++)
            {
                UpdateField updateField = updateSql.UpdateFields.ChildCollection[parameterIndex] as UpdateField;
                if (updateField == null)
                    throw new FasException(DataAccessErrorCode.Database.ParameterError, CommonStringClassKernel.DatabaseImpl_ParameterHandlerForUpdate + parameterIndex);

                FieldValue feildValue = updateSql.UpdateValues.ChildCollection[parameterIndex] as FieldValue;
                if (feildValue == null)
                    throw new FasException(DataAccessErrorCode.Database.ParameterError, CommonStringClassKernel.DatabaseImpl_ParameterHandlerForUpdate1 + parameterIndex);

                parameters.Add(ParameterHandler(db, feildValue, updateField, DataAccessOpType.U));
            }
            //****统一数据访问服务v1.2，update sql参数增加主键条件解析。
            if (updateSql.UpdateCondition.ChildCollection.Count > 0)
            {
                foreach (var filterCondition in updateSql.UpdateCondition.ChildCollection)
                {
                    if (filterCondition is SqlPrimaryKey)
                    {
                        foreach (var keyField in filterCondition.ChildCollection)
                        {
                            if (!(keyField is SqlPrimaryKeyField pkField))
                                continue; //非主键条件不做处理

                            parameters.Add(ParameterHandler(db, pkField.Value, pkField, DataAccessOpType.U));
                        }
                    }
                    else if (filterCondition is ConditionStatement condi)    //update语句支持条件
                    {
                        //与ConditionStatement.ToSQL()中生成的变量替换@Param 名称保持一致。
                        //目前只用于加入Timestamp时间戳条件
                        var paramName = condi.ConditionField.Table.TablePrefix + "_" + condi.ConditionFieldValue.ConditionFieldName;
                        parameters.Add(ParameterHandler(db, condi.ConditionFieldValue, condi.ConditionField, DataAccessOpType.U, paramName));
                    }
                }
            }

            return parameters;
        }

        /// <summary>
        /// 对Select类SQL语句进行参数处理
        /// </summary>
        /// <param name="sqlStatement">待处理的SQL语句</param>
        /// <param name="db">数据访问对象</param>
        /// <returns>处理后的参数数组</returns>
        private List<IDbDataParameter> ParameterHandlerForSelect(SqlStatement sqlStatement, ITDatabase db)
        {
            var selectSql = sqlStatement as SelectSqlStatement;
            List<IDbDataParameter> parameters = null;
            if (selectSql.FilterCondition != null)
                parameters = ParameterHandlerForSelectFunc(selectSql.FilterCondition, db);
            return parameters;
        }

        /// <summary>
        /// 对Select类SQL语句进行参数处理
        /// </summary>
        /// <param name="sqlStatement">待处理的SQL语句</param>
        /// <param name="db">数据访问对象</param>
        /// <returns>处理后的参数数组</returns>
        private List<IDbDataParameter> ParameterHandlerForSelectFunc(FilterConditionStatement condition, ITDatabase db)
        {
            var parameters = new List<IDbDataParameter>();

            if (condition?.ChildCollection == null || condition.ChildCollection.Count == 0)
                return parameters;
            foreach (var child in condition.ChildCollection)
            {
                if (child is SqlPrimaryKey primaryKey)
                {
                    foreach (var keyField in primaryKey.ChildCollection)
                    {
                        SqlPrimaryKeyField pkField = keyField as SqlPrimaryKeyField;
                        if (pkField == null)
                            throw new FasException(DataAccessErrorCode.Database.ParameterError, CommonStringClassKernel.DatabaseImpl_ParameterHandlerForSelectFunc + keyField.ToSQL());
                        parameters.Add(ParameterHandler(db, pkField.Value, pkField, DataAccessOpType.Q));
                    }
                }
                else if (child is ConditionStatement conditionStatement)
                {
                    parameters.Add(ParameterHandler(db, conditionStatement.ConditionFieldValue, conditionStatement.ConditionField, DataAccessOpType.Q, conditionStatement.ConditionFieldValue.ConditionFieldName));
                }
                else if (child is FilterConditionStatement filterConditionStatement)
                {
                    parameters.AddRange(ParameterHandlerForSelectFunc(filterConditionStatement, db));
                }
            }
            return parameters;
        }

        /// <summary>
        /// 对Select类SQL语句进行参数处理
        /// </summary>
        /// <param name="sqlStatementCondition">待处理的条件元素</param>
        /// <param name="db">数据访问对象</param>
        /// <returns>处理后的参数数组</returns>
        private List<IDbDataParameter> ParameterHandlerForSelect(FilterConditionStatement sqlStatementCondition, ITDatabase db)
        {
            List<IDbDataParameter> parameters = null;
            if (sqlStatementCondition != null)
                parameters = ParameterHandlerForSelectFunc(sqlStatementCondition, db);
            return parameters;
        }

        /// <summary>
        /// 对Select类SQL语句进行参数处理
        /// </summary>
        /// <param name="sqlStatement">待处理的SQL语句</param>
        /// <param name="db">数据访问对象</param>
        /// <returns>处理后的参数数组</returns>
        private List<IDbDataParameter> ParameterHandlerForDelete(SqlStatement sqlStatement, ITDatabase db)
        {
            var deleteSql = sqlStatement as DeleteSqlStatement;
            var parameters = new List<IDbDataParameter>();

            if (deleteSql.SubQuerySql != null)
            {
                for (int parameterIndex = 0; parameterIndex < deleteSql.SubQuerySql.Condition.ChildCollection.Count; parameterIndex++)
                {
                    var filterCondition = deleteSql.SubQuerySql.Condition.ChildCollection[parameterIndex];
                    if (filterCondition is SqlPrimaryKey)
                    {
                        foreach (var keyField in filterCondition.ChildCollection)
                        {
                            SqlPrimaryKeyField pkField = keyField as SqlPrimaryKeyField;
                            if (pkField == null)
                                throw new FasException(DataAccessErrorCode.Database.ParameterError, CommonStringClassKernel.DatabaseImpl_ParameterHandlerForDelete + parameterIndex);

                            parameters.Add(ParameterHandler(db, pkField.Value, pkField, DataAccessOpType.D));
                        }
                    }
                }
            }
            else
            {
                for (int parameterIndex = 0; parameterIndex < deleteSql.Conditions.ChildCollection.Count; parameterIndex++)
                {
                    var filterCondition = deleteSql.Conditions.ChildCollection[parameterIndex];
                    if (filterCondition is SqlPrimaryKey)
                    {
                        foreach (var keyField in filterCondition.ChildCollection)
                        {
                            SqlPrimaryKeyField pkField = keyField as SqlPrimaryKeyField;
                            if (pkField == null)
                                throw new FasException(DataAccessErrorCode.Database.ParameterError, CommonStringClassKernel.DatabaseImpl_ParameterHandlerForDelete1 + parameterIndex);

                            parameters.Add(ParameterHandler(db, pkField.Value, pkField, DataAccessOpType.D));
                        }
                    }
                }
            }

            return parameters;
        }

        /// <summary>
        /// 对Insert类SQL语句进行参数处理
        /// </summary>
        /// <param name="sqlStatement">待处理的SQL语句</param>
        /// <param name="db">数据访问对象</param>
        /// <returns>处理后的参数数组</returns>
        private List<IDbDataParameter> ParameterHandlerForInsert(SqlStatement sqlStatement, ITDatabase db)
        {
            var insertSql = sqlStatement as InsertSqlStatement;
            var parameters = new List<IDbDataParameter>(insertSql.InsertFields.ChildCollection.Count);

            for (int parameterIndex = 0; parameterIndex < insertSql.InsertFields.ChildCollection.Count; parameterIndex++)
            {
                InsertField insertField = insertSql.InsertFields.ChildCollection[parameterIndex] as InsertField;
                if (insertField == null)
                    throw new FasException(DataAccessErrorCode.Database.ParameterError, CommonStringClassKernel.DatabaseImpl_ParameterHandlerForInsert + parameterIndex);
                //FAS低代码改动：跳过CreateTime LastModifyTime的参数构造
                if (!insertField.IsUseVarBinding)
                    continue;
                InsertValue insertValue = insertSql.InsertValues.ChildCollection[parameterIndex] as InsertValue;
                if (insertValue == null)
                    throw new FasException(DataAccessErrorCode.Database.ParameterError, CommonStringClassKernel.DatabaseImpl_ParameterHandlerForInsert1 + parameterIndex);

                parameters.Add(ParameterHandler(db, insertValue, insertField, DataAccessOpType.I));
            }

            return parameters;
        }

        /// <summary>
        /// 处理特殊数据类型参数
        /// </summary>
        /// <param name="db">数据访问对象</param>
        /// <param name="parameters">参数列表</param>
        /// <param name="fieldValue">字段值</param>
        /// <param name="field">待处理字段</param>
        private IDbDataParameter ParameterHandler(ITDatabase db, FieldValue fieldValue, Field field, DataAccessOpType type, string fieldName = "")
        {
            if (string.IsNullOrEmpty(fieldName))
                fieldName = field.FieldName;
            if (type == DataAccessOpType.Q) //查询语句的SQL参数占位符需要加入表名前缀
            {

                if (!string.IsNullOrEmpty(field.Table?.TablePrefix))
                {
                    if (field is SqlPrimaryKeyField)
                    {
                        fieldName = field.FieldName;
                    }
                    else if ((field is ConditionField) && (fieldValue is ConditionFieldValue))
                    {
                        fieldName = field.Table.TablePrefix + "_" + (fieldValue as ConditionFieldValue).ConditionFieldName;
                    }
                    else
                    {
                        throw new FasException(DataAccessErrorCode.Database.ParameterError, CommonStringClassKernel.DatabaseImpl_ParameterHandler);
                    }
                }
                else
                {
                    throw new FasException(DataAccessErrorCode.Database.ParameterError, field.FieldName + CommonStringClassKernel.DatabaseImpl_ParameterHandler1);
                }
            }

            IDbDataParameter parameter;
            switch ((DataType)fieldValue.DataType)
            {
                case DataType.Binary:
                    {
                        byte[] byteArray = fieldValue.Value as byte[];
                        parameter = db.MakeInParam(fieldName, TDbDataType.Blob, byteArray);
                        break;
                    }
                case DataType.Boolean:
                    if (db.DbType == TDbType.PostgreSQL)
                    {
                        if (fieldValue.Value is bool boolVal)
                        {
                            parameter = new NpgsqlParameter(fieldName, NpgsqlDbType.Bit);
                            parameter.Value = boolVal;
                            break;
                        }
                        else if(fieldValue.Value == DBNull.Value)
                        {
                            parameter = new NpgsqlParameter(fieldName, NpgsqlDbType.Bit);
                            parameter.Value = DBNull.Value;
                            break;
                        }
                        else
                        {
                            /*
                             * 在 C# 中，当使用 Npgsql 访问 PostgreSQL 数据库时，如果你希望将 C# 中的数据类型映射到 PostgreSQL 中的 bit 类型，你可以使用以下方法指定 1 比特的值。
                             * a: 使用布尔类型： 如果你的 bit 类型的长度为 1，可以考虑使用布尔类型来表示 1 比特的值。在 C# 中，布尔类型（bool）只占用 1 个比特的内存空间，因此非常适合映射到 bit 类型。
                             * b: 使用整数类型： 如果你不想使用布尔类型，也可以使用整数类型来表示 1 比特的值。通常，0 表示假，1 表示真。
                             */
                            var inputVal = Convert.ToString(fieldValue.Value);
                            if (!bool.TryParse(inputVal, out bool value))
                            {
                                if (inputVal == "0")
                                    value = false;
                                if (inputVal == "1")
                                    value = true;
                            }
                            parameter = new NpgsqlParameter(fieldName, NpgsqlDbType.Bit);
                            parameter.Value = value;
                            break;
                        }
                    }
                    parameter = db.MakeInParam(fieldName, TDbDataType.Int, fieldValue.Value);
                    break;
                case DataType.Int:
                    parameter = db.MakeInParam(fieldName, TDbDataType.Int, fieldValue.Value);
                    break;
                case DataType.Long:
                    parameter = db.MakeInParam(fieldName, TDbDataType.Int, fieldValue.Value);
                    break;
                case DataType.Decimal:
                    parameter = db.MakeInParam(fieldName, TDbDataType.Decimal, fieldValue.Value);
                    break;
                case DataType.Timestamp:
                case DataType.Date:
                case DataType.DateTime:
                    if (db.DbType == TDbType.PostgreSQL)
                    {
                        parameter = db.MakeInParam(fieldName, fieldValue.Value);
                    }
                    else
                    {
                        parameter = db.MakeInParam(fieldName, TDbDataType.DateTime, fieldValue.Value);
                    }
                    break;
                case DataType.Time: //Time类型不能用DateTime做
                    parameter = db.MakeInParam(fieldName, fieldValue.Value);
                    break;
                case DataType.String:
                    if (EnvironmentSetting.MulitLanguage.IsEnableUnicode)
                    {
                        parameter = db.MakeInParam(fieldName, TDbDataType.NVarChar, fieldValue.Value);
                    }
                    else
                    {
                        if (fieldValue.DbColumnDataType == DatabaseColumnType.Nvarchar || fieldValue.DbColumnDataType == DatabaseColumnType.NvarcharMax)
                            parameter = db.MakeInParam(fieldName, TDbDataType.NVarChar, fieldValue.Value);
                        else
                            parameter = db.MakeInParam(fieldName, TDbDataType.VarChar, fieldValue.Value);
                    }
                    parameter.Size = -1;
                    break;
                default:
                    throw new FasException(DataAccessErrorCode.DataType.NotSupportedType, ((DataType)fieldValue.DataType).ToString());
            }
            return parameter;
        }

        #endregion

        #region 废弃方法 || 暂时没用

        /// <summary>
        /// 统一数据访问修改V1.1：
        /// 根据ModelTreeSQLBuilder获取SQL以及入参，并执行获取返回结果
        /// </summary>
        /// <param name="sql">SQL语句</param>
        /// <returns>数据</returns>
        public List<DataTable> GetDataCollection(string sql, FilterConditionStatement filterConditionStatement, string dataSourceName)
        {
            if (string.IsNullOrEmpty(sql) || string.IsNullOrEmpty(dataSourceName))
                throw new FasException(DataAccessErrorCode.Database.NullValue, CommonStringClassKernel.DatabaseImpl_GetDataCollection1);
            var dataTables = new List<DataTable>();
            try
            {
                string sqlString = sql;
                var db = GetDatabaseByConfigkey(dataSourceName);
                {
                    try
                    {
                        var parameters = new List<IDbDataParameter>();

                        if (filterConditionStatement.ChildCollection.Count > 0)
                            parameters = ParameterHandlerForSelect(filterConditionStatement, db);

                        var ds = new DataSet();
                        _localLogService.WriteSQL("分组聚合SQL输出=========>：" + sqlString, parameters?.ToArray());
                        if (parameters == null || parameters.Count == 0)
                        {
                            ds = db.ExecuteDataSet(sqlString);
                        }
                        else
                        {
                            ds = db.ExecuteDataSet(sqlString, parameters.ToArray());
                        }

                        if (ds != null)
                        {
                            int i = 0;
                            string suffix = string.Empty;
                            foreach (DataTable dt in ds.Tables)
                            {
                                if (i > 0)
                                    suffix = i.ToString();
                                dt.TableName = "Query_" + suffix;
                                dataTables.Add(dt);
                                i++;
                            }
                        }
                    }
                    catch (Exception e)
                    {
                        MonitorError(e, sqlString);
                        throw;
                    }
                }
                return dataTables;
            }
            catch (Exception e)
            {
                MonitorError(e, new string[] { });
                throw;
            }
        }


        /// <summary>
        /// 获取数据
        /// </summary>
        /// <param name="dataSourceName">数据源名称</param>
        /// <param name="sqlStrings">SQL语句</param>
        /// <param name="tableNames">表名称</param>
        /// <returns>数据集</returns>
        private DataSet GetData(string dataSourceName, string[] sqlStrings, string[] tableNames)
        {
            var db = GetDatabaseByConfigkey(dataSourceName);
            try
            {
                if (sqlStrings != null && sqlStrings.Count() > 0)
                {
                    foreach (var sql in sqlStrings)
                    {
                        _localLogService.WriteSQL($"dataSource:{dataSourceName} 查询SQL输出=========>：{sql}");
                    }
                }
                DataSet dataset = db.ExecuteDataSet(sqlStrings);
                for (int i = 0; i < tableNames.Length; i++)
                {
                    dataset.Tables[i].TableName = tableNames[i];
                }

                return dataset;
            }
            catch (Exception e)
            {
                MonitorError(e, sqlStrings);
                throw;
            }
        }

        /// <summary>
        /// 获取数据
        /// </summary>
        /// <param name="dataSourceName">数据源名称</param>
        /// <param name="sqlStrings">SQL语句</param>
        /// <param name="tableNames">表名称</param>
        /// <returns>数据集</returns>
        private DataSet GetData(string dataSourceName, string[] sqlStrings, string[] tableNames, IDbDataParameter[][] paramList)
        {
            var db = GetDatabaseByConfigkey(dataSourceName);
            {
                try
                {
                    if (sqlStrings != null && sqlStrings.Count() > 0)
                    {
                        for (int i = 0; i < sqlStrings.Count(); i++)
                        {
                            //如果参数数组没超过数组长度，则打印参数列表，否则不打印
                            var parms = sqlStrings.Count() > 0 ? paramList[i]?.ToArray() : null;
                            _localLogService.WriteSQL($"dataSource:{dataSourceName} 查询SQL输出=========>：{sqlStrings[i]}", parms);
                        }
                    }
                    DataSet dataset = db.ExecuteDataSet(sqlStrings, paramList);
                    for (int i = 0; i < tableNames.Length; i++)
                    {
                        dataset.Tables[i].TableName = tableNames[i];
                    }

                    return dataset;
                }
                catch (Exception e)
                {
                    MonitorError(e, sqlStrings);
                    throw;
                }
            }
        }
        #endregion

        #region Private Funcs
        private void MonitorError(Exception e, params string[] sqls)
        {
            if (sqls == null)
                sqls = new string[0];

            var context = new Dictionary<string, string>()
            {
                {"Error", e.ToString()},
                {"sqls",string.Join(",", sqls)}
            };

            MonitorClient.Send("DataAccessSqlError", 1, null, context);
        }

        private Dictionary<string, object> GetControlContext(SqlStatement sql)
        {
            if (sql.SqlBuildingInfo?.SqlExecuteControlInfo == null) return null;
            var context = sql.SqlBuildingInfo?.SqlExecuteControlInfo;
            Dictionary<string, object> dict = new Dictionary<string, object>();
            if (context.Timeout > 0)
                dict[DACConst.DACControlContextConst.Timeout] = context.Timeout;
            return dict;
        }
        #endregion
    }
}